#include "Pipeline.h"
#include "Logger.h"

namespace devii
{

Pipeline::Pipeline()
{
}

Pipeline::~Pipeline()
{
	for(unsigned int i = 0; i < vertex_buffers.size(); i++)
	{
		delete vertex_buffers[i];
	}

	for(unsigned int i = 0; i < index_buffers.size(); i++)
	{
		delete index_buffers[i];
	}

	context->Flush();
	context->ClearState();
	context->Release();
	device->Release();
	
}


bool Pipeline::startupD3D(const int & width, const int & height, HWND hwnd)
{
	// Initialize device and swapchain
	DXGI_SWAP_CHAIN_DESC sd;

	sd.BufferDesc.Width						= (UINT)width;
	sd.BufferDesc.Height					= (UINT)height;
	sd.BufferDesc.RefreshRate.Numerator		= 60;
	sd.BufferDesc.RefreshRate.Denominator	= 1;
	sd.BufferDesc.Format					= DXGI_FORMAT_R8G8B8A8_UNORM;
	sd.BufferDesc.ScanlineOrdering			= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
	sd.SampleDesc.Count						= 1;
	sd.SampleDesc.Quality					= 0;
	sd.BufferUsage							= DXGI_USAGE_RENDER_TARGET_OUTPUT;
	sd.BufferCount							= 1;
	sd.OutputWindow							= hwnd;
	sd.Windowed								= true; /* TODO windowed */
	sd.SwapEffect							= DXGI_SWAP_EFFECT_DISCARD;
	sd.Flags								= 0;
	
	int deviceFlags = 0;

#if defined( DEBUG ) || defined ( _DEBUG )
	deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
	D3D_FEATURE_LEVEL feature = D3D_FEATURE_LEVEL_11_0;

	// Try with D3D11 first
	HRESULT hr = D3D11CreateDeviceAndSwapChain( 0, D3D_DRIVER_TYPE_HARDWARE, 0, deviceFlags, &feature, 1,
		D3D11_SDK_VERSION, &sd, &swapchain, &device, 0, &context );
		// If succeeded the graphics support dx11
	if(SUCCEEDED(hr))
	{
		log().write("Pipeline","Initializing Direct3D 11.0 succeeded");
		this->feature_level = feature;
		return true;
	}
	// if failed, try with Dx 10.1
	else if(FAILED(hr))
	{
		log().write("Pipeline","Initializing Direct3D 11.0 failed, trying with Direct3D 10.1");
		feature = D3D_FEATURE_LEVEL_10_1;
		hr = D3D11CreateDeviceAndSwapChain( 0, D3D_DRIVER_TYPE_HARDWARE, 0, deviceFlags, &feature, 1,
		D3D11_SDK_VERSION, &sd, &swapchain, &device, 0, &context );
		
		// If success use dx 10.1
		if(SUCCEEDED(hr))
		{
			log().write("Pipeline","Initializing Direct3D 10.1 succeeded");
			this->feature_level = feature;
			return true;
		}
		// else try to initialize 10.0
		else if(FAILED(hr))
		{
			log().write("Pipeline","Initializing Direct3D 10.1 failed, trying Direct3D 10.0");
			feature = D3D_FEATURE_LEVEL_10_0;
			hr = D3D11CreateDeviceAndSwapChain( 0, D3D_DRIVER_TYPE_HARDWARE, 0, deviceFlags, &feature, 1,
			D3D11_SDK_VERSION, &sd, &swapchain, &device, 0, &context );

			// If success use 10.0
			if(SUCCEEDED(hr))
			{
				log().write("Pipeline","Initializing Direct3D 10.0 succeeded");
				this->feature_level = feature;
				return true;
			}
			// else exit and tell user that direct3D could not be initialized
			else if(FAILED(hr))
			{
				log().write("Pipeline", "Could not create any device, exiting...");
				// TODO Popup to tell the user that Direct3D could not be initialized
				return false;
			}
		}
	}	

	return true;
}

bool Pipeline::shutdown()
{
	return true;
}


void Pipeline::draw(const unsigned int start, const unsigned int nr_of_vertices)
{
	context->Draw(nr_of_vertices, start);
	
}

void Pipeline::setRenderTarget(const unsigned int nr_rendertargets, RenderTarget ** render_target, DepthBuffer * depth)
{
	//ID3D11RenderTargetView * render_targets[1] = {render_target->getRenderTarget()};

	std::vector<ID3D11RenderTargetView*> render_targets_view;
	for(unsigned int i = 0; i < nr_rendertargets; i++)
	{
		render_targets_view.push_back(render_target[i]->getRenderTarget());
	}
	context->OMSetRenderTargets(nr_rendertargets, &render_targets_view[0], depth->getDepthBuffer());
}

void Pipeline::setVertexBuffer(VertexBuffer * const vertex_buffer)
{
	// Sets Topology so Direct3D Knows whether we shall draw triangles, lines or points
	context->IASetPrimitiveTopology(vertex_buffer->getTopology());
	// Set the input-layout, this is so Direct3D know how the incoming vertex
	// shall look like
	context->IASetInputLayout(vertex_buffer->getInputLayout());
	// Finally set the vertexbuffers, this can be zero up to 15 if I remember
	// correctly
	context->IASetVertexBuffers(0, vertex_buffer->getSize(), vertex_buffer->getBuffer(), vertex_buffer->getStrides(), vertex_buffer->getOffsets());

}
void Pipeline::setIndexBuffer(IndexBuffer * const index_buffer)
{
	// Sets IndexBuffer to Direct3D, 
	// This is so we don't have to have multiple copies of the same vertex
	context->IASetIndexBuffer(index_buffer->getBuffer(), DXGI_FORMAT_D32_FLOAT, 0);

	//TODO test indexbuffer
}

void Pipeline::setVertexShader(ID3D11VertexShader* const vertex_shader)
{
	// Sets VertexShader to Direct3D
	context->VSSetShader(vertex_shader, 0, 0);
	
}
void Pipeline::setHullShader(ID3D11HullShader* const hull_shader)
{
	// Sets HullShader to Direct3D
	// Only available in Direct3D 11.0 
	context->HSSetShader(hull_shader, 0, 0);
}
void Pipeline::setDomainShader(ID3D11DomainShader* const domain_shader)
{
	// Sets DomainShader to Direct3D
	// Only available in Direct3D 11.0
	context->DSSetShader(domain_shader, 0, 0);
}
void Pipeline::setGeometryShader(ID3D11GeometryShader* const geometry_shader)
{
	// Sets GeometryShader to Direct3D
	context->GSSetShader(geometry_shader, 0, 0);
}
void Pipeline::setPixelShader(ID3D11PixelShader* const pixel_shader)
{
	// Sets PixelShader to Direct3D
	context->PSSetShader(pixel_shader, 0, 0);
}

void Pipeline::setViewports(unsigned int nr_viewports, D3D11_VIEWPORT* view_ports)
{
	// Set the viewport
	// The nr_viewports can be more than 1
	context->RSSetViewports(nr_viewports, view_ports);
}
	

void Pipeline::setupPipeline(PipelineStates* const states)
{
	context->RSSetState(states->getRasterizerState());
	context->PSSetSamplers(0, 1, states->getSamplerState());
	context->OMSetBlendState(states->getBlendState(), states->getBlendFactor(), states->getSamplemask());
}

void Pipeline::clearRenderTarget(float clear_color[], RenderTarget * const render_target)
{
	// Clears the rendertarget @render_target
	// Using the color @clear_color[]
	context->ClearRenderTargetView(render_target->getRenderTarget(), clear_color);
}

void Pipeline::clearDepthBuffer(DepthBuffer* const depth_buffer)
{
	// Clear the @depth_buffer
	// With a Direct3D 11 - flag called D3D11_CLEAR_DEPTH
	context->ClearDepthStencilView(depth_buffer->getDepthBuffer(), D3D11_CLEAR_DEPTH, 1, 0);
}

void Pipeline::swap()
{
	// This makes the swapchain present
	// Buffers is swapped so we can se the changes on the screen
	swapchain->Present(0,0);
}

VertexBuffer * Pipeline::createVertexBuffer()
{
	// Pushes the vertex_buffer to the vertex_buffers-stack
	// As well as creating a new buffer
	VertexBuffer * buffer = new VertexBuffer(device, context);
	vertex_buffers.push_back(buffer);
	return buffer;
}

IndexBuffer * Pipeline::createIndexBuffer()
{

	IndexBuffer * buffer = new IndexBuffer(device, context);
	
	index_buffers.push_back(buffer);
	return buffer;
}

ConstantBuffer*	Pipeline::createConstantBuffer()
{
	ConstantBuffer* constant_buffer = new ConstantBuffer(device, context);
	
	return constant_buffer;
}

Texture * Pipeline::createTexture(const unsigned int width, const unsigned int height, DXGI_FORMAT color_format)
{
	
	ID3D11Texture2D * d3d_texture;
	D3D11_TEXTURE2D_DESC tex_desc;

	tex_desc.Width = width;
	tex_desc.Height = height;
	tex_desc.MipLevels = 0;
	tex_desc.ArraySize = 1;
	tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
	tex_desc.SampleDesc.Count = 1;
	tex_desc.SampleDesc.Quality = 0;
	tex_desc.Usage = D3D11_USAGE_DEFAULT;
	tex_desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
	tex_desc.CPUAccessFlags = 0;
	tex_desc.MiscFlags = 0;

	ID3D11ShaderResourceView * shader_view = NULL;
	
	HRESULT hr = device->CreateTexture2D(&tex_desc, NULL, &d3d_texture);
	if(FAILED(hr))
	{
		log().write("Pipeline", "Texture2D for texture-creation failed");
		return NULL;
	}
	hr = device->CreateShaderResourceView(d3d_texture, NULL, &shader_view);
	if(FAILED(hr))
	{
		log().write("Pipeline", "ShaderResourceView failed to create for texture");
		return NULL;
	}
	log().write("Pipeline", "Texture successfully created");
	Texture * texture = new Texture(width, height);

	texture->setTexture(d3d_texture);
	texture->setTextureBuffer(shader_view);

	return texture;
}

Texture* Pipeline::createTexture(const std::string& file)
{
	ID3D11ShaderResourceView* shader_resource;

	HRESULT hr = D3DX11CreateShaderResourceViewFromFile(device, file.c_str(), 0, 0, &shader_resource, &hr );
	if(FAILED(hr))
	{
		std::stringstream ss;
		ss << "Failed to load texture-file: " << file;

		log().write("Pipeline", ss.str());
		return NULL;
	}

	Texture* texture = new Texture(0,0);

	texture->setTextureBuffer(shader_resource);
	texture->setTexture(NULL);
	texture_factory.addTexture(texture);
	return texture;

}
RenderTarget * Pipeline::createScreenRenderTarget(const unsigned int width, const unsigned int height)
{	
	// This function fetches the swapchain-buffer, and then creates a RenderTargetView of it
	// This is so we can have a swapchainbuffer as rendertarget i.e this will
	// fetch the buffer that renders to the screen

	ID3D11RenderTargetView * view = NULL;

	HRESULT hr;
	ID3D11Texture2D* texture;
	// Fetch the buffer
	hr = swapchain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&texture );
	// Create a RenderTarget of that buffer
	hr = device->CreateRenderTargetView( texture, NULL, &view );

	texture->Release();

	if(FAILED(hr))
	{
		log().write("Pipeline", "RenderTargetView failed to create for rendertarget");
		return NULL;
	}

	log().write("Pipeline","RenderTarget successfully created");
	
	RenderTarget * render_target = new RenderTarget(width, height);

	//render_target->setTexture(texture);

	render_target->setRenderTarget(view);

	texture_factory.addRenderTarget(render_target);
	return render_target;
}

RenderTarget* Pipeline::createTextureRenderTarget(const unsigned int width, const unsigned int height)
{
	// This function creates a rendertarget so we can render to a texture
	// And then for example render that texture to the screen 
	ID3D11Texture2D * texture = NULL;
	D3D11_TEXTURE2D_DESC tex_desc;
	tex_desc.Width = width;
	tex_desc.Height = height;
	tex_desc.MipLevels = 0;
	tex_desc.ArraySize = 1;
	tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
	tex_desc.SampleDesc.Count = 1;
	tex_desc.SampleDesc.Quality = 0;
	tex_desc.Usage = D3D11_USAGE_DEFAULT;
	tex_desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
	tex_desc.CPUAccessFlags = 0;
	tex_desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;

	HRESULT hr = device->CreateTexture2D(&tex_desc, NULL, &texture);
	if(FAILED(hr))
	{
		log().write("Pipeline", "Texture2D For rendertarget failed to create");
		return NULL;
	}
	
	ID3D11RenderTargetView * view = NULL;
	hr = device->CreateRenderTargetView( texture, NULL, &view );

	
	hr = device->CreateRenderTargetView(texture, NULL, &view);
	if(FAILED(hr))
	{
		log().write("Pipeline", "RenderTargetView failed to create for rendertarget");
		return NULL;
	}
	ID3D11ShaderResourceView * shader_view = NULL;
	hr = device->CreateShaderResourceView(texture, NULL, &shader_view);
	if(FAILED(hr))
	{
		log().write("Pipeline", "ShaderResourceView failed to create for rendertarget");
		return NULL;
	}

	log().write("Pipeline","RenderTarget successfully created");
	RenderTarget * render_target = new RenderTarget(width, height);

	render_target->setTexture(texture);

	render_target->setRenderTarget(view);

	render_target->setTextureBuffer(shader_view);

	texture_factory.addRenderTarget(render_target);
	return render_target;
}

DepthBuffer * Pipeline::createDepthBuffer(const unsigned int width, const unsigned int height)
{
	

	ID3D11Texture2D * depth_map;
	D3D11_TEXTURE2D_DESC tex_desc;

	// The bufferdesc which have many options
	tex_desc.Width = width;
	tex_desc.Height = height;
	tex_desc.MipLevels = 1;
	tex_desc.ArraySize = 1;
	tex_desc.Format = DXGI_FORMAT_R32_TYPELESS;
	tex_desc.SampleDesc.Count = 1;
	tex_desc.SampleDesc.Quality = 0;
	tex_desc.Usage = D3D11_USAGE_DEFAULT;
	tex_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
	tex_desc.CPUAccessFlags = 0;
	tex_desc.MiscFlags = 0;

	ID3D11ShaderResourceView * shader_view = NULL;
	// Begin with creating the texture
	HRESULT hr = device->CreateTexture2D(&tex_desc, NULL, &depth_map);
	if(FAILED(hr))
	{
		log().write("Pipeline", "Creating Texture2D for depthmap succeeded");
		return NULL;
	}
	// If succeeded create a depthstencildescription
	D3D11_DEPTH_STENCIL_VIEW_DESC depth_desc;
	ZeroMemory(&depth_desc, sizeof(depth_desc));
	ID3D11DepthStencilView * depth_view = NULL;
	depth_desc.Format = DXGI_FORMAT_D32_FLOAT;
	depth_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
	depth_desc.Texture2D.MipSlice = NULL;

	// Create the view
	device->CreateDepthStencilView(depth_map, &depth_desc, &depth_view);
	if(FAILED(hr))
	{
		log().write("Pipeline", "Create DepthStencilView for depthmap succeeded");
		return NULL;
	}

	// If succeeded create the shaderresourceview so we can set this as a texture down to the shaders
	// Useful when for example using shadowmaps

	D3D11_SHADER_RESOURCE_VIEW_DESC shader_desc;
	shader_desc.Format = DXGI_FORMAT_R32_FLOAT;
	shader_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
	shader_desc.Texture2D.MipLevels = 1;
	shader_desc.Texture2D.MostDetailedMip = 0;

	
	device->CreateShaderResourceView(depth_map, &shader_desc, &shader_view);
	if(FAILED(hr))
	{
		log().write("Pipeline", "Creating ShaderResourceView for depthmap succeeded, creating buffer...");
		return NULL;
	}
	DepthBuffer * buffer = new DepthBuffer(width, height);
	buffer->setDepthBuffer(depth_view);
	buffer->setShaderResource(shader_view);

	depth_map->Release();

	texture_factory.addDepthBuffer(buffer);
	log().write("Pipeline", "DepthBuffer successfully created");

	return buffer;
}

PipelineStates*	Pipeline::createPipelineStates()
{
	return new PipelineStates();
}

ID3D11VertexShader* Pipeline::createVertexShader(const std::string& file, const std::string& function,
	VertexBuffer * const buffer, D3D11_INPUT_ELEMENT_DESC* input_desc, const int nr_of_elements)
{
	// The params @input_desc and @nr_of_elements is so we here create
	// a inputlayout together with the vertexbuffer, this is how
	// Direct3D will know how the vertex will look like

	ID3D10Blob* blob;
	ID3D10Blob* errors;
	ID3D11VertexShader* vertex_shader = 0;
	std::string shader_version;

	// Dependent on which Direct3D-version currently is initialized
	if(feature_level == D3D_FEATURE_LEVEL_11_0)
	{
		shader_version = "vs_5_0";
	}
	else if(feature_level == D3D_FEATURE_LEVEL_10_1)
	{
		shader_version = "vs_4_1";
	}
	else if(feature_level == D3D_FEATURE_LEVEL_10_0)
	{
		shader_version = "vs_4_0";
	}

	HRESULT hr = D3DX11CompileFromFile( file.c_str(), 0, 0, function.c_str(), 
		shader_version.c_str(), 0, 0, 0, &blob, &errors, 0 );

	
	// In case there were any errors or warnings in the shaderfunction, tell in a messagebox
	// And print to log
	if(errors)
	{
		MessageBox(NULL,(char*)errors->GetBufferPointer(), 0, 0);
		log().write("Pipeline", "There were some errors when compiled VertexShader:");
		log().write("VertexShaderError", (char*)errors->GetBufferPointer());
		return NULL;
	}

	// Create vertexshader
	hr = device->CreateVertexShader(blob->GetBufferPointer(), blob->GetBufferSize(), 0, &vertex_shader);

	// if CreateVertexShader failed, return hr-code
	if(FAILED(hr))
	{
		return NULL;
	}

	// If we have input to the shader
	if(input_desc)
	{
		ID3D11InputLayout* input_layout = NULL;
		device->CreateInputLayout(input_desc, nr_of_elements, blob->GetBufferPointer(), blob->GetBufferSize(), &input_layout);
		buffer->setInputLayout(input_layout);
	}
	return vertex_shader;
}
ID3D11HullShader* Pipeline::createHullShader(const std::string& file, const std::string& function)
{
	ID3D10Blob* blob;
	ID3D10Blob* errors;
	ID3D11HullShader* hull_shader = 0;

	std::string shader_version;

	if(feature_level == D3D_FEATURE_LEVEL_11_0)
	{
		shader_version = "hs_5_0";
	}
	else if(feature_level == D3D_FEATURE_LEVEL_10_1)
	{
		log().write("Pipeline", "Can't create hullshaders in Direct3D 10.1 or lower");
		return NULL;
	}
	else if(feature_level == D3D_FEATURE_LEVEL_10_0)
	{
		log().write("Pipeline", "Can't create hullshaders in Direct3D 10.1 or lower");
		return NULL;
	}

	HRESULT hr = D3DX11CompileFromFile( file.c_str(), 0, 0, function.c_str(), shader_version.c_str(), 0, 0, 0, &blob, &errors, 0 );

	
	// In case there were any errors or warnings in the shaderfunction, tell in a messagebox
	if(errors)
	{
		MessageBox(NULL,(char*)errors->GetBufferPointer(), 0, 0);
		log().write("Pipeline", "There were some errors when compiled HullShader:");
		log().write("HullShaderError", (char*)errors->GetBufferPointer());
		return NULL;
	}

	// Create vertexshader
	hr = device->CreateHullShader(blob->GetBufferPointer(), blob->GetBufferSize(), 0, &hull_shader);

	// if CreateVertexShader failed, return hr-code
	if(FAILED(hr))
	{
		return NULL;
	}

	//vertex_blob = blob;
	return hull_shader;
}
ID3D11DomainShader* Pipeline::createDomainShader(const std::string& file, const std::string& function)
{
	ID3D10Blob* blob;
	ID3D10Blob* errors;
	ID3D11DomainShader* domain_shader = 0;

	std::string shader_version;

	if(feature_level == D3D_FEATURE_LEVEL_11_0)
	{
		shader_version = "ds_5_0";
	}
	else if(feature_level == D3D_FEATURE_LEVEL_10_1)
	{
		log().write("Pipeline", "Can't create domainshaders in Direct3D 10.1 or lower");
		return NULL;
	}
	else if(feature_level == D3D_FEATURE_LEVEL_10_0)
	{
		log().write("Pipeline", "Can't create domainshaders in Direct3D 10.1 or lower");
		return NULL;
	}

	HRESULT hr = D3DX11CompileFromFile( file.c_str(), 0, 0, function.c_str(), shader_version.c_str(), 0, 0, 0, &blob, &errors, 0 );

	
	// In case there were any errors or warnings in the shaderfunction, tell in a messagebox
	if(errors)
	{
		MessageBox(NULL,(char*)errors->GetBufferPointer(), 0, 0);
			log().write("Pipeline", "There were some errors when compiled DomainShader:");
		log().write("DomainShaderError", (char*)errors->GetBufferPointer());
		return NULL;
	}

	// Create vertexshader
	hr = device->CreateDomainShader(blob->GetBufferPointer(), blob->GetBufferSize(), 0, &domain_shader);

	// if CreateVertexShader failed, return hr-code
	if(FAILED(hr))
	{
		return NULL;
	}

	//vertex_blob = blob;
	return domain_shader;
}
ID3D11GeometryShader* Pipeline::createGeometryShader(const std::string& file, const std::string& function)
{
	ID3D10Blob* blob;
	ID3D10Blob* errors;
	ID3D11GeometryShader* geometry_shader = 0;
	std::string shader_version;

	if(feature_level == D3D_FEATURE_LEVEL_11_0)
	{
		shader_version = "gs_5_0";
	}
	else if(feature_level == D3D_FEATURE_LEVEL_10_1)
	{
		shader_version = "gs_4_1";
	}
	else if(feature_level == D3D_FEATURE_LEVEL_10_0)
	{
		shader_version = "gs_4_0";
	}
	HRESULT hr = D3DX11CompileFromFile( file.c_str(), 0, 0, function.c_str(), shader_version.c_str(), 0, 0, 0, &blob, &errors, 0 );

	
	// In case there were any errors or warnings in the shaderfunction, tell in a messagebox
	if(errors)
	{
		MessageBox(NULL,(char*)errors->GetBufferPointer(), 0, 0);
		log().write("Pipeline", "There were some errors when compiled GeometryShader:");
		log().write("GeometryShaderError", (char*)errors->GetBufferPointer());
		return NULL;
	}

	// Create vertexshader
	hr = device->CreateGeometryShader(blob->GetBufferPointer(), blob->GetBufferSize(), 0, &geometry_shader);

	// if CreateVertexShader failed, return hr-code
	if(FAILED(hr))
	{
		return NULL;
	}

	//vertex_blob = blob;
	return geometry_shader;
}
ID3D11PixelShader* Pipeline::createPixelShader(const std::string& file, const std::string& function)
{
	ID3D10Blob* blob;
	ID3D10Blob* errors;
	ID3D11PixelShader* pixel_shader = 0;

	std::string shader_version;

	if(feature_level == D3D_FEATURE_LEVEL_11_0)
	{
		shader_version = "ps_5_0";
	}
	else if(feature_level == D3D_FEATURE_LEVEL_10_1)
	{
		shader_version = "ps_4_1";
	}
	else if(feature_level == D3D_FEATURE_LEVEL_10_0)
	{
		shader_version = "ps_4_0";
	}
	HRESULT hr = D3DX11CompileFromFile( file.c_str(), 0, 0, function.c_str(), shader_version.c_str(), 0, 0, 0, &blob, &errors, 0 );

	
	// In case there were any errors or warnings in the shaderfunction, tell in a messagebox
	if(errors)
	{
		MessageBox(NULL,(char*)errors->GetBufferPointer(), 0, 0);
		log().write("Pipeline", "There were some errors when compiled PixelShader:");
		log().write("PixelShaderError", (char*)errors->GetBufferPointer());
		return NULL;
	}

	// Create vertexshader
	hr = device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), 0, &pixel_shader);

	// if CreateVertexShader failed, return hr-code
	if(FAILED(hr))
	{
		return NULL;
	}

	//vertex_blob = blob;
	return pixel_shader;
}

}/* devii */